﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Text.RegularExpressions;
using System.Net;
using System.Web.Services.Description;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Reflection;
using System.Xml.Serialization;
using System.Xml;
using System.IO;

namespace Zyg.Utility
{
    public class WebServiceUtility
    {
        /// <summary>
        /// 动态调用WebService
        /// </summary>
        /// <param name="strUrl">WebService的url地址，例如：http://localhost/WebService.asmx</param>
        /// <param name="strNamespace">WebService的命名空间</param>
        /// <param name="strClassName">WebService的类名</param>
        /// <param name="strMethodName">要调用的WebService的方法名</param>
        /// <param name="op">参数</param>
        public static object TryWebService(string strUrl, string strNamespace, string strClassName, string strMethodName, params object[] op)
        {
            try
            {
                // 1. 使用 WebClient 下载 WSDL 信息
                WebClient web = new WebClient();
                Stream stream = web.OpenRead(strUrl + "?WSDL");

                // 2. 创建和格式化 WSDL 文档
                ServiceDescription description = ServiceDescription.Read(stream);

                // 3. 创建客户端代理代理类
                ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
                importer.ProtocolName = "Soap"; // 指定访问协议。

                importer.Style = ServiceDescriptionImportStyle.Client; // 生成客户端代理。
                importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerationOptions.GenerateNewAsync;

                importer.AddServiceDescription(description, null, null); // 添加 WSDL 文档

                // 4. 使用 CodeDom 编译客户端代理类
                CodeNamespace nmspace = new CodeNamespace(); // 为代理类添加命名空间，缺省为全局空间
                if (!string.IsNullOrEmpty(strNamespace))
                {
                    nmspace = new CodeNamespace(strNamespace);
                }

                CodeCompileUnit unit = new CodeCompileUnit();
                unit.Namespaces.Add(nmspace);

                ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit);
                CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");

                CompilerParameters parameter = new CompilerParameters();
                parameter.GenerateExecutable = false;
                parameter.GenerateInMemory = true;
                parameter.ReferencedAssemblies.Add("System.dll");
                parameter.ReferencedAssemblies.Add("System.XML.dll");
                parameter.ReferencedAssemblies.Add("System.Web.Services.dll");
                parameter.ReferencedAssemblies.Add("System.Data.dll");

                CompilerResults result = provider.CompileAssemblyFromDom(parameter, unit);

                // 5. 使用 Reflection 调用 WebService
                if (!result.Errors.HasErrors)
                {
                    Assembly asm = result.CompiledAssembly;

                    Type t = asm.GetType(strClassName); // 如果在前面为代理类添加了命名空间，此处需要将命名空间添加到类型前面
                    if (!string.IsNullOrEmpty(strNamespace))
                    {
                        t = asm.GetType(strNamespace + "." + strClassName);
                    }

                    object o = Activator.CreateInstance(t);

                    try
                    {
                        MethodInfo method = t.GetMethod(strMethodName);

                        return method.Invoke(o, op);
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                }
                else
                {
                    throw new Exception("调用WebServices出错");
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }
}
